﻿#pragma once
#ifndef __RPC_CLIENT_HPP__
#define __RPC_CLIENT_HPP__

#include<memory>
#include<string>
#include<functional>
#include"../Base/Network/Client.hpp"
#include"../Base/Tools/DllLoader.hpp"
#include"../Base/Tools/ObjectPool.hpp"
#include"../Base/Network/NetworkDef.hpp"
#include"../Base/Network/Session.hpp"
#include"../Base/Serialize/SerialBuffer.hpp"
#include"../Base/Serialize/SerialVector.hpp"
#include"../Base/Serialize/SerialMap.hpp"

namespace MMFNetwork
{
    //前置声明
    class BinaryDispatch;
    class Client;
}

namespace SC_SUN
{

    class RpcClient
    {

        std::shared_ptr<MMFNetwork::Client> mClient;                ///< 客户端对象
        std::shared_ptr<MMFNetwork::BinaryDispatch> mDispatcher;    ///< 消息派发器
        std::string mRemoteIp;                                      ///< 远端ip地址
        uint16_t mRemotePort;                                       ///< 远端端口号
        std::function<void(bool)> mStatusHandler;                   ///< 外部的链接状态回调
        MMF::ObjectPool<std::vector<char>> mSerialInPool;
    
    public:

        RpcClient(const std::string& remoteIp, uint16_t remotePort, const std::function<void(bool)>& statasHandler);
        ~RpcClient();

        bool Start();
        void Stop();

        bool Send(void* buff, uint32_t count);
        bool Recv(void* buff, uint32_t count);
        bool RecvPkg(void* buff, uint32_t count);


        std::shared_ptr<MMFNetwork::BinaryDispatch> Dispatcher();
        std::shared_ptr<MMFNetwork::Client> Client();
        std::vector<char>& GetSerialInBuffer() {return mSerialInPool.GetObject();}

        //发送网络消息
        template<typename T>
        void SendMsg(const char* msgName, T msg)
        {
            using namespace MMFNetwork;
            using namespace MMFSerialize;

            uint32_t headLen = CalcMessageHeadLen(msgName);
            std::vector<char>& iBuff = GetSerialInBuffer();
            MMFSerialize::SerialInBuffer iSBuff(iBuff.data() + headLen, (uint32_t)iBuff.size() - headLen);
            iSBuff >> msg;
            uint32_t total = FillMessageHead(iBuff, headLen, msgName, iSBuff.mPos);
            Send(iBuff.data(), total);
        }

        //解析网络消息
        template<typename T>
        void ParseMessage(MMFNetwork::MMFMessageHeader* pkg, T& msg)
        {
            char* data = pkg->mName + pkg->mNameBytes;
            MMFSerialize::SerialOutBuffer out(data, pkg->mDataBytes - (uint32_t(pkg->mName - (char*)pkg) + pkg->mNameBytes));
            out << msg;
        }

        //接收网络消息
        template<typename T>
        void RecvMsg(T& msg)
        {
            std::vector<char>& buff = GetSerialInBuffer();
            RecvPkg(buff.data(), buff.size());
            ParseMessage<T>((MMFNetwork::MMFMessageHeader*)buff.data(), msg);
        }
    };

}


#endif